-- HeartBeatM
-- Create by panyl
-- 客户端心跳功能模块

module("HeartBeatM", package.seeall);

-- 最近一次心跳回应的时间
local ack = 0;
local ping = 0;

-- 是否开启心跳
local switch = false;

-- 整个回路时间记录
local route = {};

local whenACK;

-- 模块初始化
function init()
    MSG.registerMsgTrigger("HeartBeatM", "MSG_PING", whenACK);
    MSG.registerMsgTrigger("HeartBeatM", "MSG_LOGIN_NOTIFY_OK", function(para)
        -- 开启心跳
        start();
    end);
    MSG.registerMsgTrigger("HeartBeatM", "MSG_RELOGIN", function(para)
        if para.code == 1 then
            -- 重连成功
            start();
        end
    end);
end

-- 开启心跳
function start()
    -- 判断网络是否正常
    if not Socket.isConnected() then
        return;
    end

    switch = true;

    -- 初始化数据
    ack  = os.time();
    ping = os.time();

    route = {};
end

-- 关闭心跳
function stop()
    switch = false;
end

-- 心跳
function update()
    if DEBUG_MODE == 1 then
        -- debug模式不用ping，免得gs刷trace
        return;
    end

    -- 如果关闭状态中
    if not switch then
        return;
    end
    
    -- 如果太久没有回应了，就认为网络需要重连了(暂定1分钟)
    local curTime = os.time();
    if curTime > ack + 60 then
        -- 直接断开连接，会自动触发重连机制
        Socket.disconnect();

        -- 先断开，重连成功再开启
        stop();
        return;
    end

    -- 5秒钟一次
    if ping + 5 >= curTime then
        return;
    end

    -- 最近一次发起ping的时间
    ping = curTime;

    -- 把太旧的数据清掉
    for cookie, _ in pairs(table.keys(route)) do
        if cookie + 100 < curTime then
            route[cookie] = nil;
        end
    end

    -- 先记录一下
    local cookie = curTime;
    route[cookie] = MAX_VALUE;

    -- 如果没有网络，也不需要ping了，因为必定失败
    if not Socket.isConnected() then
        return;
    end

   Communicate.send("CMD_PING", { ["cookie"] = cookie, });
end

whenACK = function(para)
    local cookie = para.cookie;

    -- 回应事件，key和value对比就知道延时了
    if route[cookie] then
        route[cookie] = os.time();
    end

    -- 更新最近一次有回应的ping时间
    if ack < cookie then
        ack = cookie;
    end
end
